package com.market.socket;

import bean.ChatMessage;
import cn.dev33.satoken.same.SaSameUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.market.constants.ResultCode;
import com.market.exception.ServiceException;
import com.market.feign.Agent;
import com.market.service.ChatMessageService;
import com.market.service.UserService;
import com.market.service.impl.ChatMessageServiceImpl;
import com.market.service.impl.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket/{roomId}/{userId}")
@Component
@Slf4j
public class WebSocketServer {
  public static void setUserService(ApplicationContext context) {
    userService = context.getBean(UserServiceImpl.class);
    redisTemplate=context.getBean(StringRedisTemplate.class);
    chatMessageService=context.getBean(ChatMessageServiceImpl.class);
    agent=context.getBean(Agent.class);
  }
  
  public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

  private static UserService userService;
  private static ChatMessageService chatMessageService;
  private static StringRedisTemplate redisTemplate;


  private static Agent agent;
  @OnOpen
  public void onOpen(Session session, @PathParam("userId") String userId) {
    if (StrUtil.isNotEmpty(userId)) {
      // 加入新用户
      if (sessionMap.containsKey(userId)) {
        sessionMap.remove(userId);
      }
      sessionMap.put(userId, session);
      log.info("上线，userId={}, 当前在线人数为：{}", userId, sessionMap.size());
    }
  }
  
  /**
   * 处理客户端发送的WebSocket消息
   * 接收消息并转发，同时保存到Redis中
   * @param message 客户端发送的消息内容
   * @param session 当前WebSocket会话
   * @param userId 当前用户ID
   */
  @OnMessage
  public void onMessage(String message, Session session, @PathParam("userId") String userId) {
    // 记录接收到的消息日志
    log.info("服务端收到id={}的消息:{}", userId, message);
    
    // 将接收到的消息解析为JSON对象
    JSONObject jsonObject = JSON.parseObject(message);
    
    // 提取接收者用户ID
    String toUserId = jsonObject.getString("toUserId");
    // 验证接收者ID是否为空
    if(StrUtil.isEmpty(toUserId)) throw new ServiceException(ResultCode.Fail);
    
    // 提取发送者用户ID
    String fromUserId = jsonObject.getString("fromUserId");
    // 验证发送者ID是否为空
    if (StrUtil.isEmpty(fromUserId)) throw new ServiceException(ResultCode.Fail);
    
    // 提取聊天会话ID
    String roomId = jsonObject.getString("chatListId");
    
    // 获取接收者的WebSocket会话
    Session toSession = sessionMap.get(toUserId);

    String isImage = jsonObject.getString("isImage");
    if(isImage.equals("1")){
      jsonObject.put("isRead","0");
      jsonObject.put("isAi","1");
      // 将消息存储到Redis列表中，使用聊天会话ID作为键
      redisTemplate.opsForList().rightPush("chat:message:" + roomId, jsonObject.toJSONString());
      // 记录消息发送成功的日志
      log.info("图片分析成功url={}", jsonObject.getString("content"));
    }
    
    // 如果接收者在线（会话存在）
    if (null != toSession) {
      // 标记消息为已读状态
      jsonObject.put("isRead","1");
      jsonObject.put("isAi","0");
      // 将消息存储到Redis列表中，使用聊天会话ID作为键
      redisTemplate.opsForList().rightPush("chat:message:" + roomId, jsonObject.toJSONString());
      // 立即发送消息给接收者
      this.sendMessage(message, toSession);
      // 记录消息发送成功的日志
      log.info("发送给用户userId={}，消息：{}", toUserId, message);
    } else if (isImage.equals("0")){
      //获取商品发布者id
      String productUserId = jsonObject.getString("productUserId");
      if(productUserId.equals(fromUserId)){//商品发布者消息不使用AI回复
        jsonObject.put("isRead", "0");
        jsonObject.put("isAi", "0");
        redisTemplate.opsForList().rightPush("chat:message:" + roomId, jsonObject.toJSONString());
        // 记录消息发送失败的日志
        log.info("发送失败，用户username={}未上线", toUserId);
      }else {
        //接收者不在线AI接管
        //将发送者的消息存储到redis列表中，等待用户上线后接收
        jsonObject.put("isRead", "0");
        jsonObject.put("isAi", "0");
        redisTemplate.opsForList().rightPush("chat:message:" + roomId, jsonObject.toJSONString());
        //组装向AI的聊天消息
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setChatListId(roomId);
        chatMessage.setFromUserId(toUserId);
        chatMessage.setToUserId(fromUserId);
        StringBuffer content = new StringBuffer();
//        content.append("图片描述:"+jsonObject.getString("analysis"));
//        content.append("用户表示(ID)是：" + fromUserId);
//        content.append("商品的标识(ID)是：" + jsonObject.getString("productId"));
        content.append("对话消息是："+jsonObject.getString("content"));
        chatMessage.setContent(content.toString());
        chatMessage.setImageAnalysis(jsonObject.getString( "analysis"));
        chatMessage.setProductId(jsonObject.getString("productId"));
        chatMessage.setUserId(fromUserId);
        chatMessage.setIsWebSearch(jsonObject.getString("isWebSearch"));
        String aiContent = agent.userChat(chatMessage);

        //组装向接收者的聊天消息
        jsonObject.put("fromUserId", toUserId);
        jsonObject.put("toUserId", fromUserId);
        jsonObject.put("chatListId", roomId);
        jsonObject.put("content",aiContent);
        jsonObject.put("isAi", "1");
        jsonObject.put("is_image","0");
        String aiMessage = jsonObject.toJSONString();
        //获取发送者的WebSocket会话
        Session fromSession = sessionMap.get(fromUserId);

        this.sendMessage(aiMessage, fromSession);
        // 如果接收者不在线
        // 标记消息为未读状态
        jsonObject.put("isRead", "0");
        jsonObject.put("isAi", "1");
        // 将接收者消息存储到Redis列表中，等待用户上线后接收
        redisTemplate.opsForList().rightPush("chat:message:" + roomId, jsonObject.toJSONString());
        // 记录消息发送失败的日志
        log.info("用户username={}未上线,AI接管", toUserId);
      }

    }
  }
  /**
   * 服务端发送消息给客户端
   */
  private void sendMessage(String message, Session toSession) {
    try {
      log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
      toSession.getBasicRemote().sendText(message);
    } catch (Exception e) {
      log.error("服务端发送消息给客户端失败", e);
    }
  }
  
  @OnClose
  public void onClose(Session session, @PathParam("roomId") String roomId,@PathParam("userId") String userId) {
    ListOperations<String, String> operations = redisTemplate.opsForList();
    List<String> messageList = operations.range("chat:message:" + roomId, 0, -1);
    if(!messageList.isEmpty()){
      boolean result = chatMessageService.saveList(messageList);
      if (result) redisTemplate.delete("chat:message:" + roomId);
    }
    sessionMap.remove(userId);
    log.info("userId={}下线, 当前在线人数为：{}", userId, sessionMap.size());
  }
  
  @OnError
  public void onError(Session session, Throwable error) {
    log.error("发生错误");
    log.error(error.toString());
  }
}
